const express = require('express');
const multer = require('multer');
const sharp = require('sharp');
const cors = require('cors');
const path = require('path');
const fs = require('fs');

const app = express();
const PORT = process.env.PORT || 3000;

// 健康检查端点
app.get('/health', (req, res) => {
  res.status(200).send('OK');
});

// 创建上传目录
const uploadsDir = path.join(__dirname, 'uploads');
const compressedDir = path.join(__dirname, 'compressed');
if (!fs.existsSync(uploadsDir)) fs.mkdirSync(uploadsDir);
if (!fs.existsSync(compressedDir)) fs.mkdirSync(compressedDir);

// 中间件配置
app.use(cors());
app.use(express.json());
app.use(express.static('public'));

// Multer配置
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, uploadsDir);
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 10 * 1024 * 1024 // 10MB
  },
  fileFilter: function (req, file, cb) {
    const allowedTypes = /jpeg|jpg|png|webp|gif/;
    const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
    const mimetype = allowedTypes.test(file.mimetype);

    if (mimetype && extname) {
      return cb(null, true);
    } else {
      cb(new Error('只支持JPEG、PNG、WebP和GIF格式的图片'));
    }
  }
});

// 文件清理函数
function cleanupFiles(filePath) {
  setTimeout(() => {
    if (fs.existsSync(filePath)) {
      fs.unlinkSync(filePath);
    }
  }, 300000); // 5分钟后删除文件
}

// 图片压缩API
app.post('/api/compress', upload.single('image'), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: '没有上传文件' });
    }

    const quality = parseInt(req.body.quality) || 80;
    const format = req.body.format || 'jpeg';
    const inputPath = req.file.path;
    const outputFileName = `compressed_${Date.now()}.${format}`;
    const outputPath = path.join(compressedDir, outputFileName);

    // 获取原图信息
    const originalStats = fs.statSync(inputPath);
    const originalSize = originalStats.size;

    // 使用sharp进行压缩
    let sharpInstance = sharp(inputPath);

    // 根据格式设置压缩选项
    let options = {};
    switch (format) {
      case 'jpeg':
        options = { quality: quality, mozjpeg: true };
        break;
      case 'png':
        options = { compressionLevel: Math.floor((100 - quality) / 10), palette: true };
        break;
      case 'webp':
        options = { quality: quality };
        break;
      case 'gif':
        options = { colors: Math.max(2, Math.floor(quality * 2.56)) }; // 质量转换为颜色数
        break;
    }

    // 执行压缩
    const buffer = await sharpInstance[format](options).toBuffer();

    // 保存压缩后的图片
    fs.writeFileSync(outputPath, buffer);

    // 获取压缩后文件信息
    const compressedStats = fs.statSync(outputPath);
    const compressedSize = compressedStats.size;
    const compressionRatio = ((originalSize - compressedSize) / originalSize * 100).toFixed(2);

    // 获取图片尺寸信息
    const metadata = await sharp(inputPath).metadata();

    // 清理文件
    cleanupFiles(inputPath);
    cleanupFiles(outputPath);

    res.json({
      success: true,
      originalFile: {
        name: req.file.originalname,
        size: originalSize,
        sizeFormatted: formatFileSize(originalSize),
        width: metadata.width,
        height: metadata.height
      },
      compressedFile: {
        name: outputFileName,
        size: compressedSize,
        sizeFormatted: formatFileSize(compressedSize),
        width: metadata.width,
        height: metadata.height,
        url: `/api/download/${outputFileName}`
      },
      compressionRatio: compressionRatio
    });

  } catch (error) {
    console.error('压缩错误:', error);
    res.status(500).json({ error: '图片压缩失败: ' + error.message });
  }
});

// 批量压缩API
app.post('/api/batch-compress', upload.array('images', 10), async (req, res) => {
  try {
    if (!req.files || req.files.length === 0) {
      return res.status(400).json({ error: '没有上传文件' });
    }

    const quality = parseInt(req.body.quality) || 80;
    const format = req.body.format || 'jpeg';
    const results = [];

    for (const file of req.files) {
      try {
        const outputFileName = `compressed_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.${format}`;
        const outputPath = path.join(compressedDir, outputFileName);

        // 获取原图信息
        const originalStats = fs.statSync(file.path);
        const originalSize = originalStats.size;

        // 使用sharp进行压缩
        let options = {};
        switch (format) {
          case 'jpeg':
            options = { quality: quality, mozjpeg: true };
            break;
          case 'png':
            options = { compressionLevel: Math.floor((100 - quality) / 10), palette: true };
            break;
          case 'webp':
            options = { quality: quality };
            break;
          case 'gif':
            options = { colors: Math.max(2, Math.floor(quality * 2.56)) }; // 质量转换为颜色数
            break;
        }

        const buffer = await sharp(file.path)[format](options).toBuffer();
        fs.writeFileSync(outputPath, buffer);

        // 获取压缩后文件信息
        const compressedStats = fs.statSync(outputPath);
        const compressedSize = compressedStats.size;
        const compressionRatio = ((originalSize - compressedSize) / originalSize * 100).toFixed(2);

        // 获取图片尺寸信息
        const metadata = await sharp(file.path).metadata();

        results.push({
          originalFile: {
            name: file.originalname,
            size: originalSize,
            sizeFormatted: formatFileSize(originalSize),
            width: metadata.width,
            height: metadata.height
          },
          compressedFile: {
            name: outputFileName,
            size: compressedSize,
            sizeFormatted: formatFileSize(compressedSize),
            width: metadata.width,
            height: metadata.height,
            url: `/api/download/${outputFileName}`
          },
          compressionRatio: compressionRatio
        });

        // 清理文件
        cleanupFiles(file.path);
        cleanupFiles(outputPath);

      } catch (error) {
        console.error(`批量压缩错误 ${file.originalname}:`, error);
        results.push({
          originalFile: { name: file.originalname },
          error: error.message
        });
      }
    }

    res.json({ success: true, results });

  } catch (error) {
    console.error('批量压缩错误:', error);
    res.status(500).json({ error: '批量压缩失败: ' + error.message });
  }
});

// 文件下载API
app.get('/api/download/:filename', (req, res) => {
  const filename = req.params.filename;
  const filePath = path.join(compressedDir, filename);

  if (fs.existsSync(filePath)) {
    // 获取原始文件名（如果存在）
    const originalName = req.query.original || filename;

    // 设置正确的文件名编码
    res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(originalName)}`);
    res.setHeader('Content-Type', 'application/octet-stream');

    // 读取并发送文件
    const fileStream = fs.createReadStream(filePath);
    fileStream.pipe(res);

    fileStream.on('error', (err) => {
      console.error('文件流错误:', err);
      if (!res.headersSent) {
        res.status(500).json({ error: '文件下载失败' });
      }
    });
  } else {
    res.status(404).json({ error: '文件不存在' });
  }
});

// 辅助函数：格式化文件大小
function formatFileSize(bytes) {
  if (bytes === 0) return '0 B';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

// 启动服务器
app.listen(PORT, () => {
  console.log(`图片压缩工具服务器运行在 http://localhost:${PORT}`);
});

module.exports = app;